﻿#r "System.Xml.Linq"
open System
open System.Xml
open System.Xml.Linq
let nullToOpt x = if box x = null then None else Some x
let flip f b a = f a b
let replace (target:string) value (text:string) = text.Replace(target,value)

module IOLayer = 
    open System.IO
    let ``app.config path`` = Path.Combine(__SOURCE_DIRECTORY__,"Dcm.Tests","app.config")
    if File.Exists ``app.config path`` = false then 
        failwithf "Expected to find app.config at %s" ``app.config path``
    let private info = FileInfo(``app.config path``)
    if info.Attributes.HasFlag FileAttributes.ReadOnly then
        info.IsReadOnly <- false
    let outPath = Path.Combine(__SOURCE_DIRECTORY__,"Dcm.Tests","bin","Debug")

let xDoc = XDocument.Load IOLayer.``app.config path``
let rootNs = xDoc.Root.Name.Namespace
let getElement (node:XElement) name = node.Element(rootNs + name) // |> nullToOpt
let getElements (node:XElement) name = node.Elements(rootNs + name) //|> Seq.map nullToOpt
let getAttrib (node:XElement) name = node.Attribute(XNamespace.None + name)

let getAttribValueOrNull node name  = 
    let v = getAttrib node name
    if v <> null then v.Value else null

let setAttribValue name value (node:XElement) = node.SetAttributeValue(XNamespace.None + name,value)
let isNotNull x = box x <> null
let dcmSection = getElement xDoc.Root "DynamicConfigurationSection"

let getConfigMapsWith section name = 
    getElements section "configMap"
    |> Seq.filter (flip getAttribValueOrNull name >> isNotNull)
let fixupAConfigAttr name getStr =
    let fixupIteration i v = 
        setAttribValue name (getStr i) v
    getConfigMapsWith dcmSection name
    |> Seq.iteri fixupIteration

let fixupAssemblyPath outPath = 
    let getStr i = 
        if i > 0 then 
            sprintf "file:///%s/DynamicConfigurationManager.DLL" (replace "\\" "/"  outPath)
        else
            "file:///C:\DynamicConfigurationManager.dll"
    fixupAConfigAttr "assemblyPath" getStr

let fixupAssemblyPathRegEx outPath = 
    let getStr i = 
        if i = 0 then 
            @"file:///.*/DynamicConfigurationManager\.DLL"
        else 
            "^$"
    fixupAConfigAttr "assemblyPathRegEx" getStr

let fixupHostNameRegexNodes machineName =
    let makeBadLetter l = if l = 'B' then 'C' else 'B'
    let willNotMatchRegex = String ([| '^'; Seq.head machineName |> makeBadLetter |])
    let willMatchRegex = String ([|'^'; Seq.head machineName |])
    let fixupIteration i v = 
        let str = if i = 0 || i = 2 then willNotMatchRegex else willMatchRegex
        setAttribValue "hostnameRegEx" str v
    getConfigMapsWith dcmSection "hostnameRegEx"
    |> Seq.iteri fixupIteration

let fixupHostnameNodes machineName = 
    let fixupIteration i v = 
        let badMatch = String ( [| machineName |> Seq.head |] )
        let str = if i = 0 then badMatch else machineName
        setAttribValue "hostname"  str v
    getConfigMapsWith dcmSection "hostname"
    |> Seq.iteri fixupIteration

let fixupExecutablePathNodes() = 
    let fixupIteration i v =
        let badMatch = "."
        let str = if i=2 then badMatch else IOLayer.outPath
        setAttribValue "executablePath" str v
    getConfigMapsWith dcmSection "executablePath"
    |> Seq.iteri fixupIteration


fixupAssemblyPath IOLayer.outPath
fixupAssemblyPathRegEx IOLayer.outPath
fixupHostNameRegexNodes Environment.MachineName
fixupHostnameNodes Environment.MachineName
fixupExecutablePathNodes()
xDoc.Save( IOLayer.``app.config path`` )

